import React, { useEffect, useRef, useState, useCallback } from 'react'
import { Tooltip } from 'antd'
import type { PerformanceMetrics, TrackEvent } from '../utils/performance'

// --------------------------
// 1. 高级图表配置（视觉+布局）
// --------------------------
const CHART_CONFIG = {
  // 布局：上下间距增大，避免重叠
  topPadding: 60, // 顶部留白
  chartSpacing: 120, // 图表间垂直间距
  titleHeight: 36, // 标题高度
  chartHeight: 220, // 单个图表高度
  bottomPadding: 80, // 底部留白
  // 视觉：高级风格配置
  colors: {
    coreMetric: [
      '#40a9ff',
      '#52c41a',
      '#fa8c16',
      '#f5222d',
      '#722ed1',
      '#1890ff',
      '#52c41a',
      '#fa8c16',
    ],
    resource: '#4ecdc4',
    memory: '#ff6b6b',
    event: [
      '#96ceb4',
      '#ffeaa7',
      '#dda0dd',
      '#ff9f43',
      '#1dd1a1',
      '#ff6b9d',
      '#c44569',
    ],
  },
  axisColor: '#eef1f5', // 坐标轴浅灰
  textColor: '#1d2129', // 主文本深灰
  subTextColor: '#86909c', // 次要文本浅灰
  gridColor: '#f7f8fa', // 网格线颜色
  // 高级效果：渐变/阴影
  shadow: '0 4px 12px rgba(0,0,0,0.06)', // 元素阴影
  gradientOpacity: 0.8, // 渐变透明度
}

// 计算总画布高度：动态适配4个图表
const getTotalHeight = () => {
  return (
    CHART_CONFIG.topPadding +
    4 * (CHART_CONFIG.titleHeight + CHART_CONFIG.chartHeight) +
    3 * CHART_CONFIG.chartSpacing + // 4个图表间共3个间距
    CHART_CONFIG.bottomPadding
  )
}

// --------------------------
// 2. 组件Props类型
// --------------------------
interface PerformanceVizCanvasProps {
  metrics: PerformanceMetrics
  events?: TrackEvent[]
  width?: number
  height?: number // 默认为动态计算的总高度
}

const PerformanceVizCanvas: React.FC<PerformanceVizCanvasProps> = ({
  metrics,
  events = [],
  width: propsWidth,
  height = getTotalHeight(),
}) => {
  const canvasRef = useRef<HTMLCanvasElement>(null)
  const containerRef = useRef<HTMLDivElement>(null)
  const [hoverData, setHoverData] = useState<{
    type: 'core' | 'resource' | 'memory' | 'event'
    value: any
    pos: { x: number; y: number } // hover位置，用于Tooltip定位
  } | null>(null)
  const [canvasSize, setCanvasSize] = useState({ width: 0, height })
  const [animateProgress, setAnimateProgress] = useState(0) // 动画进度（0→1）

  // --------------------------
  // 3. 初始化：画布自适应+动画启动
  // --------------------------
  useEffect(() => {
    const updateSize = () => {
      if (containerRef.current) {
        setCanvasSize({
          width: propsWidth || containerRef.current.clientWidth - 40, // 减去容器内边距
          height,
        })
      }
    }

    // 启动入场动画（0.5s过渡）
    const timer = setTimeout(() => setAnimateProgress(1), 50)
    updateSize()
    window.addEventListener('resize', updateSize)

    return () => {
      clearTimeout(timer)
      window.removeEventListener('resize', updateSize)
    }
  }, [propsWidth, height])

  // --------------------------
  // 4. 数据处理：保持原始维度，优化格式
  // --------------------------
  const getCoreMetrics = useCallback((): Array<{
    label: string
    value: number
  }> => {
    if (!metrics) return []
    const coreKeys = [
      { key: 'pageLoadTime', label: '页面加载时间' },
      { key: 'firstPaint', label: '首次绘制(FP)' },
      { key: 'firstContentfulPaint', label: '首次内容绘制(FCP)' },
      { key: 'domInteractive', label: 'DOM可交互时间' },
      { key: 'domComplete', label: 'DOM完成时间' },
    ]
    return coreKeys
      .filter(
        (item) => metrics[item.key as keyof PerformanceMetrics] !== undefined
      )
      .map((item) => ({
        label: item.label,
        value: Number(metrics[item.key as keyof PerformanceMetrics]) || 0,
      }))
  }, [metrics])

  const getResourceData = useCallback((): Array<{
    label: string
    value: number
  }> => {
    if (!metrics?.resourceLoadTime) return []
    return Object.entries(metrics.resourceLoadTime)
      .filter(
        ([key]) =>
          key.includes('.js') || key.includes('.css') || key.includes('image')
      )
      .map(([key, value]) => ({
        label: key.length > 20 ? `${key.slice(0, 17)}...` : key, // 优化长名称显示
        value: Number(value) || 0,
      }))
  }, [metrics?.resourceLoadTime])

  const getMemoryData = useCallback((): Array<{
    label: string
    value: number
  }> => {
    if (!metrics) return []
    const baseMemory = metrics.memoryUsage
      ? Number(metrics.memoryUsage) / 1024 / 1024
      : 0
    return [
      { label: '初始内存', value: Number(baseMemory.toFixed(2)) },
      { label: '峰值内存', value: Number((baseMemory * 1.2).toFixed(2)) },
    ]
  }, [metrics])

  const getEventData = useCallback((): Array<{
    label: string
    value: number
    percentage: number
  }> => {
    if (!events.length) return []
    const total = events.reduce((sum, event) => sum + 1, 0)
    const eventCount: Record<string, number> = {}
    events.forEach((event) => {
      eventCount[event.eventName] = (eventCount[event.eventName] || 0) + 1
    })
    return Object.entries(eventCount)
      .map(([name, value]) => ({
        label: name,
        value,
        percentage: Math.round((value / total) * 100),
      }))
      .sort((a, b) => b.value - a.value) // 按频次排序
  }, [events])

  // --------------------------
  // 5. 工具函数：高级绘制能力
  // --------------------------
  // 创建线性渐变（用于柱子/扇区）
  const createLinearGradient = (
    ctx: CanvasRenderingContext2D,
    x: number,
    y: number,
    width: number,
    height: number,
    color: string
  ) => {
    // 1. 校验参数是否为有效数字（排除 NaN、Infinity 等）
    const isValid = [x, y, width, height].every(
      (num) => typeof num === 'number' && !isNaN(num) && isFinite(num)
    );
  
    if (!isValid) {
      console.error('Invalid parameters for gradient:', { x, y, width, height });
      // 返回一个默认的纯色作为降级方案，避免 Canvas 崩溃
      ctx.fillStyle = color;
      return color; // 或返回 null，由调用方处理
    }
  
    // 2. 确保宽高为非负值（避免反向渐变或无效尺寸）
    const safeWidth = Math.max(0, width);
    const safeHeight = Math.max(0, height);
  
    // 3. 提取基础颜色（处理透明度）
    const baseColor = color.length > 7 ? color.slice(0, 7) : color;
  
    // 4. 创建垂直渐变（从 (x,y) 到 (x, y + safeHeight)）
    const gradient = ctx.createLinearGradient(x, y, x, y + safeHeight);
    
    // 5. 添加渐变色标（确保色标值在 0-1 范围内）
    gradient.addColorStop(0, color);
    gradient.addColorStop(1, `${baseColor}33`); // 尾部添加透明度（如 #ffffff33）
  
    return gradient;
  };
  

  // 绘制带阴影的矩形（用于柱子）
  const drawShadowRect = (
    ctx: CanvasRenderingContext2D,
    x: number,
    y: number,
    width: number,
    height: number,
    color: string
  ) => {
    ctx.save()
    // 阴影配置
    ctx.shadowColor = CHART_CONFIG.shadow
    ctx.shadowBlur = 8
    ctx.shadowOffsetY = 4
    // 渐变填充
    const gradient = createLinearGradient(ctx, x, y, width, height, color)
    ctx.fillStyle = gradient
    ctx.fillRect(x, y, width, height)
    ctx.restore()
  }

  // 绘制带阴影的圆形（用于折线图数据点）
  const drawShadowCircle = (
    ctx: CanvasRenderingContext2D,
    x: number,
    y: number,
    radius: number,
    color: string
  ) => {
    ctx.save()
    ctx.shadowColor = CHART_CONFIG.shadow
    ctx.shadowBlur = 6
    ctx.shadowOffsetY = 3
    ctx.beginPath()
    ctx.arc(x, y, radius, 0, Math.PI * 2)
    ctx.fillStyle = color
    ctx.fill()
    // 白色描边，增强层次感
    ctx.strokeStyle = '#fff'
    ctx.lineWidth = 2
    ctx.stroke()
    ctx.restore()
  }

  // --------------------------
  // 6. 鼠标交互：精准分区+位置记录
  // --------------------------
  const handleMouseMove = useCallback(
    (e: React.MouseEvent<HTMLCanvasElement>) => {
      if (!canvasRef.current || !metrics) return
      const canvas = canvasRef.current
      const rect = canvas.getBoundingClientRect()
      const mouseX = e.clientX - rect.left
      const mouseY = e.clientY - rect.top
      const coreData = getCoreMetrics()
      const resourceData = getResourceData()
      const memoryData = getMemoryData()
      const eventData = getEventData()

      // 计算每个图表的Y轴范围（分层布局，避免重叠）
      const chartYRange = (index: number) => {
        const start =
          CHART_CONFIG.topPadding +
          index * (CHART_CONFIG.titleHeight + CHART_CONFIG.chartHeight) +
          index * CHART_CONFIG.chartSpacing
        const end = start + CHART_CONFIG.titleHeight + CHART_CONFIG.chartHeight
        return { start, end, titleY: start + CHART_CONFIG.titleHeight / 2 }
      }

      // 6.1 核心指标图表hover
      const coreRange = chartYRange(0)
      if (
        mouseY >= coreRange.start &&
        mouseY <= coreRange.end &&
        coreData.length
      ) {
        const barWidth = (canvasSize.width - 240) / coreData.length
        const hoverIndex = coreData.findIndex((_, idx) => {
          const barX = 120 + idx * barWidth
          return mouseX >= barX && mouseX <= barX + barWidth - 12
        })
        if (hoverIndex !== -1) {
          setHoverData({
            type: 'core',
            value: { ...coreData[hoverIndex], unit: 'ms' },
            pos: { x: e.clientX, y: e.clientY },
          })
          return
        }
      }

      // 6.2 资源加载图表hover
      const resourceRange = chartYRange(1)
      if (
        mouseY >= resourceRange.start &&
        mouseY <= resourceRange.end &&
        resourceData.length
      ) {
        const pointWidth =
          (canvasSize.width - 240) / (resourceData.length - 1 || 1)
        const hoverIndex = resourceData.findIndex((_, idx) => {
          const pointX = 120 + idx * pointWidth
          return mouseX >= pointX - 8 && mouseX <= pointX + 8
        })
        if (hoverIndex !== -1) {
          setHoverData({
            type: 'resource',
            value: { ...resourceData[hoverIndex], unit: 'ms' },
            pos: { x: e.clientX, y: e.clientY },
          })
          return
        }
      }

      // 6.3 内存图表hover
      const memoryRange = chartYRange(2)
      if (
        mouseY >= memoryRange.start &&
        mouseY <= memoryRange.end &&
        memoryData.length
      ) {
        const barWidth = (canvasSize.width - 320) / memoryData.length
        const hoverIndex = memoryData.findIndex((_, idx) => {
          const barX = 160 + 60 + idx * barWidth
          return mouseX >= barX && mouseX <= barX + barWidth - 12
        })
        if (hoverIndex !== -1) {
          setHoverData({
            type: 'memory',
            value: { ...memoryData[hoverIndex], unit: 'MB' },
            pos: { x: e.clientX, y: e.clientY },
          })
          return
        }
      }

      // 6.4 埋点事件图表hover
      const eventRange = chartYRange(3)
      if (
        mouseY >= eventRange.start &&
        mouseY <= eventRange.end &&
        eventData.length
      ) {
        const pieX = 200
        const pieY =
          eventRange.start +
          CHART_CONFIG.titleHeight +
          CHART_CONFIG.chartHeight / 2
        const pieRadius = 70
        const dx = mouseX - pieX
        const dy = mouseY - pieY
        const distance = Math.sqrt(dx * dx + dy * dy)

        if (distance <= pieRadius) {
          const total = eventData.reduce((sum, item) => sum + item.value, 0)
          let startAngle = 0
          for (let i = 0; i < eventData.length; i++) {
            const angle = (eventData[i].value / total) * Math.PI * 2
            const endAngle = startAngle + angle
            const mouseAngle = Math.atan2(dy, dx)
            const normalizedAngle =
              mouseAngle < 0 ? mouseAngle + 2 * Math.PI : mouseAngle

            if (normalizedAngle >= startAngle && normalizedAngle <= endAngle) {
              setHoverData({
                type: 'event',
                value: eventData[i],
                pos: { x: e.clientX, y: e.clientY },
              })
              return
            }
            startAngle = endAngle
          }
        }
      }

      setHoverData(null)
    },
    [
      canvasSize,
      metrics,
      getCoreMetrics,
      getResourceData,
      getMemoryData,
      getEventData,
    ]
  )

  const handleMouseLeave = () => setHoverData(null)

  // --------------------------
  // 7. Canvas渲染：分层绘制+高级效果
  // --------------------------
  useEffect(() => {
    if (!canvasRef.current || !metrics || canvasSize.width === 0) return
    const canvas = canvasRef.current
    const ctx = canvas.getContext('2d')
    if (!ctx) return

    // 重置画布（高清适配）
    const dpr = window.devicePixelRatio || 1
    canvas.width = canvasSize.width * dpr
    canvas.height = canvasSize.height * dpr
    ctx.scale(dpr, dpr) // 解决模糊问题
    ctx.clearRect(0, 0, canvasSize.width, canvasSize.height)
    ctx.font =
      '14px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif'
    ctx.lineCap = 'round' // 线条端点圆角，更精致

    // 计算每个图表的起始位置（分层布局）
    const getChartStart = (index: number) => {
      return (
        CHART_CONFIG.topPadding +
        index * (CHART_CONFIG.titleHeight + CHART_CONFIG.chartHeight) +
        index * CHART_CONFIG.chartSpacing
      )
    }

    // --------------------------
    // 7.1 图表1：核心性能指标（渐变柱状图+动画）
    // --------------------------
    const coreData = getCoreMetrics()
    const coreStart = getChartStart(0)
    const coreTitleY = coreStart + CHART_CONFIG.titleHeight / 2
    const coreChartY = coreStart + CHART_CONFIG.titleHeight

    // 标题：加粗+右移
    ctx.font =
      '18px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif'
    ctx.fontWeight = '600'
    ctx.fillStyle = CHART_CONFIG.textColor
    ctx.fillText('1. 核心性能指标', 50, coreTitleY)
    ctx.font =
      '14px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif'
    ctx.fontWeight = 'normal'

    if (coreData.length) {
      const maxValue = Math.max(...coreData.map((item) => item.value)) * 1.1
      const barWidth = (canvasSize.width - 240) / coreData.length

      // 网格线
      ctx.strokeStyle = CHART_CONFIG.gridColor
      ctx.lineWidth = 1
      for (let i = 0; i <= 5; i++) {
        const tickY =
          coreChartY +
          CHART_CONFIG.chartHeight -
          (i / 5) * CHART_CONFIG.chartHeight
        ctx.beginPath()
        ctx.moveTo(120, tickY)
        ctx.lineTo(canvasSize.width - 120, tickY)
        ctx.stroke()
      }

      // Y轴
      ctx.strokeStyle = CHART_CONFIG.axisColor
      ctx.lineWidth = 1.5
      ctx.beginPath()
      ctx.moveTo(120, coreChartY)
      ctx.lineTo(120, coreChartY + CHART_CONFIG.chartHeight)
      ctx.stroke()

      // Y轴刻度+文本
      ctx.fillStyle = CHART_CONFIG.subTextColor
      ctx.textAlign = 'right'
      for (let i = 0; i <= 5; i++) {
        const tickValue = Math.round((maxValue / 5) * i)
        const tickY =
          coreChartY +
          CHART_CONFIG.chartHeight -
          (tickValue / maxValue) * CHART_CONFIG.chartHeight
        // 刻度线
        ctx.beginPath()
        ctx.moveTo(116, tickY)
        ctx.lineTo(120, tickY)
        ctx.stroke()
        // 刻度文本
        ctx.fillText(`${tickValue}ms`, 110, tickY + 4)
      }

      // 渐变柱状图（带动画）
      coreData.forEach((item, idx) => {
        const barX = 120 + idx * barWidth
        const barMaxHeight = (item.value / maxValue) * CHART_CONFIG.chartHeight
        const barHeight = barMaxHeight * animateProgress // 动画进度控制高度
        const barY = coreChartY + CHART_CONFIG.chartHeight - barHeight
        const color =
          CHART_CONFIG.colors.coreMetric[
            idx % CHART_CONFIG.colors.coreMetric.length
          ]

        // 带阴影的渐变柱子
        drawShadowRect(ctx, barX, barY, barWidth - 12, barHeight, color)

        // 数值标签（动画同步显示）
        if (animateProgress > 0.5) {
          ctx.fillStyle = CHART_CONFIG.textColor
          ctx.textAlign = 'center'
          ctx.fillText(
            `${Math.round(item.value)}ms`,
            barX + (barWidth - 12) / 2,
            barY - 10
          )
        }

        // 名称标签
        ctx.fillStyle = CHART_CONFIG.subTextColor
        ctx.textAlign = 'center'
        ctx.fillText(
          item.label,
          barX + (barWidth - 12) / 2,
          coreChartY + CHART_CONFIG.chartHeight + 22
        )
      })
    } else {
      // 空数据提示
      ctx.fillStyle = CHART_CONFIG.subTextColor
      ctx.textAlign = 'center'
      ctx.fillText(
        '暂无核心性能指标数据',
        canvasSize.width / 2,
        coreChartY + CHART_CONFIG.chartHeight / 2
      )
    }

    // --------------------------
    // 7.2 图表2：资源加载耗时（平滑折线图+渐变填充）
    // --------------------------
    const resourceData = getResourceData()
    const resourceStart = getChartStart(1)
    const resourceTitleY = resourceStart + CHART_CONFIG.titleHeight / 2
    const resourceChartY = resourceStart + CHART_CONFIG.titleHeight

    // 标题
    ctx.font =
      '18px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif'
    ctx.fontWeight = '600'
    ctx.fillStyle = CHART_CONFIG.textColor
    ctx.fillText('2. 资源加载耗时', 120, resourceTitleY)
    ctx.font =
      '14px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif'
    ctx.fontWeight = 'normal'

    if (resourceData.length) {
      const maxValue = Math.max(...resourceData.map((item) => item.value)) * 1.1
      const pointWidth =
        (canvasSize.width - 240) / (resourceData.length - 1 || 1)

      // 网格线
      ctx.strokeStyle = CHART_CONFIG.gridColor
      ctx.lineWidth = 1
      for (let i = 0; i <= 5; i++) {
        const tickY =
          resourceChartY +
          CHART_CONFIG.chartHeight -
          (i / 5) * CHART_CONFIG.chartHeight
        ctx.beginPath()
        ctx.moveTo(120, tickY)
        ctx.lineTo(canvasSize.width - 120, tickY)
        ctx.stroke()
      }

      // Y轴
      ctx.strokeStyle = CHART_CONFIG.axisColor
      ctx.lineWidth = 1.5
      ctx.beginPath()
      ctx.moveTo(120, resourceChartY)
      ctx.lineTo(120, resourceChartY + CHART_CONFIG.chartHeight)
      ctx.stroke()

      // Y轴刻度
      ctx.fillStyle = CHART_CONFIG.subTextColor
      ctx.textAlign = 'right'
      for (let i = 0; i <= 5; i++) {
        const tickValue = Math.round((maxValue / 5) * i)
        const tickY =
          resourceChartY +
          CHART_CONFIG.chartHeight -
          (tickValue / maxValue) * CHART_CONFIG.chartHeight
        ctx.beginPath()
        ctx.moveTo(116, tickY)
        ctx.lineTo(120, tickY)
        ctx.stroke()
        ctx.fillText(`${tickValue}ms`, 110, tickY + 4)
      }

      // X轴
      ctx.beginPath()
      ctx.moveTo(120, resourceChartY + CHART_CONFIG.chartHeight)
      ctx.lineTo(
        canvasSize.width - 120,
        resourceChartY + CHART_CONFIG.chartHeight
      )
      ctx.stroke()

      // 折线图：带渐变填充（动画同步）
      ctx.save()
      ctx.beginPath()
      // 起点（左下方）
      ctx.moveTo(120, resourceChartY + CHART_CONFIG.chartHeight)
      // 数据点连线
      resourceData.forEach((item, idx) => {
        const pointX = 120 + idx * pointWidth
        const pointY =
          resourceChartY +
          CHART_CONFIG.chartHeight -
          (item.value / maxValue) * CHART_CONFIG.chartHeight * animateProgress
        if (idx === 0) ctx.moveTo(pointX, pointY)
        else ctx.lineTo(pointX, pointY)
      })
      // 终点（右下方）
      const lastPointX = 120 + (resourceData.length - 1) * pointWidth
      ctx.lineTo(lastPointX, resourceChartY + CHART_CONFIG.chartHeight)
      ctx.closePath()

      // 渐变填充（下到上透明）
      const gradient = ctx.createLinearGradient(
        120,
        resourceChartY + CHART_CONFIG.chartHeight,
        120,
        resourceChartY
      )
      gradient.addColorStop(0, `${CHART_CONFIG.colors.resource}22`)
      gradient.addColorStop(1, `${CHART_CONFIG.colors.resource}00`)
      ctx.fillStyle = gradient
      ctx.fill()

      // 绘制折线（加粗）
      ctx.beginPath()
      resourceData.forEach((item, idx) => {
        const pointX = 120 + idx * pointWidth
        const pointY =
          resourceChartY +
          CHART_CONFIG.chartHeight -
          (item.value / maxValue) * CHART_CONFIG.chartHeight * animateProgress
        if (idx === 0) ctx.moveTo(pointX, pointY)
        else ctx.lineTo(pointX, pointY)
      })
      ctx.strokeStyle = CHART_CONFIG.colors.resource
      ctx.lineWidth = 3
      ctx.stroke()
      ctx.restore()

      // 数据点（带阴影，动画同步放大）
      resourceData.forEach((item, idx) => {
        const pointX = 120 + idx * pointWidth
        const pointY =
          resourceChartY +
          CHART_CONFIG.chartHeight -
          (item.value / maxValue) * CHART_CONFIG.chartHeight * animateProgress
        const radius = 5 * animateProgress + 1 // 动画从1px放大到6px
        drawShadowCircle(
          ctx,
          pointX,
          pointY,
          radius,
          CHART_CONFIG.colors.resource
        )

        // 资源名称标签
        if (
          idx === 0 ||
          idx === Math.floor(resourceData.length / 2) ||
          idx === resourceData.length - 1
        ) {
          ctx.fillStyle = CHART_CONFIG.subTextColor
          ctx.textAlign = 'center'
          ctx.fillText(
            item.label,
            pointX,
            resourceChartY + CHART_CONFIG.chartHeight + 22
          )
        }
      })
    } else {
      ctx.fillStyle = CHART_CONFIG.subTextColor
      ctx.textAlign = 'center'
      ctx.fillText(
        '暂无资源加载数据',
        canvasSize.width / 2,
        resourceChartY + CHART_CONFIG.chartHeight / 2
      )
    }

    // --------------------------
    // 7.3 图表3：内存使用（双柱对比+渐变）
    // --------------------------
    const memoryData = getMemoryData()
    const memoryStart = getChartStart(2)
    const memoryTitleY = memoryStart + CHART_CONFIG.titleHeight / 2
    const memoryChartY = memoryStart + CHART_CONFIG.titleHeight

    // 标题
    ctx.font =
      '18px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif'
    ctx.fontWeight = '600'
    ctx.fillStyle = CHART_CONFIG.textColor
    ctx.fillText('3. 内存使用情况', 120, memoryTitleY)
    ctx.font =
      '14px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif'
    ctx.fontWeight = 'normal'

    if (memoryData.length) {
      const maxValue = Math.max(...memoryData.map((item) => item.value)) * 1.2
      const barWidth = (canvasSize.width - 360) / memoryData.length

      // 网格线
      ctx.strokeStyle = CHART_CONFIG.gridColor
      ctx.lineWidth = 1
      for (let i = 0; i <= 5; i++) {
        const tickY =
          memoryChartY +
          CHART_CONFIG.chartHeight -
          (i / 5) * CHART_CONFIG.chartHeight
        ctx.beginPath()
        ctx.moveTo(160, tickY)
        ctx.lineTo(canvasSize.width - 120, tickY)
        ctx.stroke()
      }

      // Y轴
      ctx.strokeStyle = CHART_CONFIG.axisColor
      ctx.lineWidth = 1.5
      ctx.beginPath()
      ctx.moveTo(160, memoryChartY)
      ctx.lineTo(160, memoryChartY + CHART_CONFIG.chartHeight)
      ctx.stroke()

      // Y轴刻度
      ctx.fillStyle = CHART_CONFIG.subTextColor
      ctx.textAlign = 'right'
      for (let i = 0; i <= 5; i++) {
        const tickValue = ((maxValue / 5) * i).toFixed(1)
        const tickY =
          memoryChartY +
          CHART_CONFIG.chartHeight -
          (Number(tickValue) / maxValue) * CHART_CONFIG.chartHeight
        ctx.beginPath()
        ctx.moveTo(156, tickY)
        ctx.lineTo(160, tickY)
        ctx.stroke()
        ctx.fillText(`${tickValue}MB`, 150, tickY + 4)
      }

      // 内存柱子（带动画+渐变）
      memoryData.forEach((item, idx) => {
        const barX = 160 + 60 + idx * barWidth
        const barMaxHeight = (item.value / maxValue) * CHART_CONFIG.chartHeight
        const barHeight = barMaxHeight * animateProgress
        const barY = memoryChartY + CHART_CONFIG.chartHeight - barHeight

        // 渐变柱子（红色系，区分初始/峰值）- 使用正确的颜色格式
        const color =
          idx === 0
            ? `${CHART_CONFIG.colors.memory}e0`
            : CHART_CONFIG.colors.memory

        drawShadowRect(ctx, barX, barY, barWidth - 12, barHeight, color)

        // 数值标签（动画同步）
        if (animateProgress > 0.5) {
          ctx.fillStyle = CHART_CONFIG.textColor
          ctx.textAlign = 'center'
          ctx.fillText(
            `${item.value.toFixed(2)}MB`,
            barX + (barWidth - 12) / 2,
            barY - 10
          )
        }

        // 名称标签
        ctx.fillStyle = CHART_CONFIG.subTextColor
        ctx.fontWeight = '500'
        ctx.textAlign = 'right'
        ctx.fillText(item.label, barX - 15, barY + barHeight / 2 + 6)
        ctx.fontWeight = 'normal'
      })
    } else {
      ctx.fillStyle = CHART_CONFIG.subTextColor
      ctx.textAlign = 'center'
      ctx.fillText(
        '暂无内存使用数据',
        canvasSize.width / 2,
        memoryChartY + CHART_CONFIG.chartHeight / 2
      )
    }

    // --------------------------
    // 7.4 图表4：埋点事件频次（环形饼图+图例优化）
    // --------------------------
    const eventData = getEventData()
    const eventStart = getChartStart(3)
    const eventTitleY = eventStart + CHART_CONFIG.titleHeight / 2
    const eventChartY = eventStart + CHART_CONFIG.titleHeight

    // 标题
    ctx.font =
      '18px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif'
    ctx.fontWeight = '600'
    ctx.fillStyle = CHART_CONFIG.textColor
    ctx.fillText('4. 埋点事件触发频次', 220, eventTitleY)
    ctx.font =
      '14px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif'
    ctx.fontWeight = 'normal'

    if (eventData.length) {
      const total = eventData.reduce((sum, item) => sum + item.value, 0)
      const pieX = 220
      const pieY = eventChartY + CHART_CONFIG.chartHeight / 2
      const outerRadius = 70
      const innerRadius = 30

      // 绘制环形扇区（带动画+渐变）
      let startAngle = -Math.PI / 2 // 从顶部开始
      eventData.forEach((item, idx) => {
        const angle = (item.value / total) * Math.PI * 2 * animateProgress
        const endAngle = startAngle + angle
        const color =
          CHART_CONFIG.colors.event[idx % CHART_CONFIG.colors.event.length]

        // 扇区渐变
        const gradient = ctx.createRadialGradient(
          pieX,
          pieY,
          innerRadius,
          pieX,
          pieY,
          outerRadius
        )
        gradient.addColorStop(0, color)
        gradient.addColorStop(1, `${color}80`)

        // 绘制环形扇区
        ctx.save()
        ctx.beginPath()
        ctx.arc(pieX, pieY, outerRadius, startAngle, endAngle)
        ctx.arc(pieX, pieY, innerRadius, endAngle, startAngle, true)
        ctx.closePath()
        // 阴影
        ctx.shadowColor = CHART_CONFIG.shadow
        ctx.shadowBlur = 8
        ctx.shadowOffsetY = 4
        ctx.fillStyle = gradient
        ctx.fill()
        ctx.restore()

        // 扇区标签线
        if (animateProgress > 0.7) {
          const midAngle = startAngle + angle / 2
          const labelX = pieX + (outerRadius + 15) * Math.cos(midAngle)
          const labelY = pieY + (outerRadius + 15) * Math.sin(midAngle)
          ctx.beginPath()
          ctx.moveTo(
            pieX + outerRadius * Math.cos(midAngle),
            pieY + outerRadius * Math.sin(midAngle)
          )
          ctx.lineTo(labelX, labelY)
          ctx.strokeStyle = CHART_CONFIG.subTextColor
          ctx.lineWidth = 1
          ctx.stroke()
        }

        startAngle = endAngle
      })

      // 环形中心文本
      if (animateProgress > 0.5) {
        ctx.fillStyle = CHART_CONFIG.textColor
        ctx.textAlign = 'center'
        ctx.fontWeight = '600'
        ctx.font =
          '16px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif'
        ctx.fillText(`总计`, pieX, pieY - 8)
        ctx.fillText(`${total}次`, pieX, pieY + 16)
        ctx.fontWeight = 'normal'
        ctx.font =
          '14px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif'
      }

      // 右侧图例
      const legendCol1X = canvasSize.width - 320
      const legendCol2X = canvasSize.width - 160
      const itemsPerColumn = Math.ceil(eventData.length / 2)

      eventData.forEach((item, idx) => {
        const isSecondColumn = idx >= itemsPerColumn
        const legendX = isSecondColumn ? legendCol2X : legendCol1X
        const legendY =
          eventChartY + 40 + (isSecondColumn ? idx - itemsPerColumn : idx) * 36
        const color =
          CHART_CONFIG.colors.event[idx % CHART_CONFIG.colors.event.length]

        // 颜色块
        ctx.save()
        ctx.shadowColor = CHART_CONFIG.shadow
        ctx.shadowBlur = 4
        ctx.fillStyle = color
        ctx.roundRect(legendX, legendY, 18, 18, 4)
        ctx.fill()
        ctx.restore()

        // 图例文本
        ctx.fillStyle = CHART_CONFIG.subTextColor
        ctx.textAlign = 'left'
        ctx.fillText(`${item.label}`, legendX + 28, legendY + 14)
        ctx.fillStyle = CHART_CONFIG.textColor
        ctx.fillText(
          `${item.value}次 (${item.percentage}%)`,
          legendX + 28,
          legendY + 34
        )
      })
    } else {
      ctx.fillStyle = CHART_CONFIG.subTextColor
      ctx.textAlign = 'center'
      ctx.fillText(
        '暂无埋点事件数据',
        canvasSize.width / 2,
        eventChartY + CHART_CONFIG.chartHeight / 2
      )
    }
  }, [
    canvasSize,
    metrics,
    events,
    animateProgress,
    getCoreMetrics,
    getResourceData,
    getMemoryData,
    getEventData,
  ])

  // --------------------------
  // 8. Tooltip内容
  // --------------------------
  const getTooltipContent = () => {
    if (!hoverData) return null
    switch (hoverData.type) {
      case 'core':
        return `${hoverData.value.label}：${Math.round(hoverData.value.value)}${
          hoverData.value.unit
        }`
      case 'resource':
        return `${hoverData.value.label}：${Math.round(hoverData.value.value)}${
          hoverData.value.unit
        }`
      case 'memory':
        return `${hoverData.value.label}：${hoverData.value.value.toFixed(2)}${
          hoverData.value.unit
        }`
      case 'event':
        return (
          <div>
            <div>{hoverData.value.label}</div>
            <div>触发频次：{hoverData.value.value}次</div>
            <div>占比：{hoverData.value.percentage}%</div>
          </div>
        )
      default:
        return null
    }
  }

  // --------------------------
  // 9. 组件渲染
  // --------------------------
  return (
    <div
      ref={containerRef}
      style={{
        width: '100%',
        height: '100%',
        margin: '20px 0',
        padding: '0 20px',
        overflow: 'hidden',
      }}
    >
      <Tooltip
        open={!!hoverData} // 修复：将visible改为open
        title={getTooltipContent()}
        placement='top'
        mouseEnterDelay={0.1}
        styles={{
          // 修复：将overlayStyle改为styles
          root: {
            maxWidth: '300px',
            padding: '8px 12px',
            borderRadius: '6px',
            boxShadow: CHART_CONFIG.shadow,
          },
        }}
        getPopupContainer={() => document.body}
      >
        <canvas
          ref={canvasRef}
          width={canvasSize.width}
          height={canvasSize.height}
          style={{
            width: '100%',
            height: '100%',
            border: '1px solid #f0f0f0',
            borderRadius: '12px',
            backgroundColor: '#fff',
            boxShadow: CHART_CONFIG.shadow,
            padding: '20px 0',
          }}
          onMouseMove={handleMouseMove}
          onMouseLeave={handleMouseLeave}
        />
      </Tooltip>
    </div>
  )
}

export default PerformanceVizCanvas
